package com.personal.dao.enums;

import java.util.Locale;
import java.util.regex.Pattern;

import com.personal.dao.metadata.DataBaseFieldMetadata;
import com.personal.dao.util.DaoUtil;
import com.personal.dao.util.ThreeTuple;
import com.personal.dao.util.TwoTuple;

/**
 * 操作类型
 * @author cuibo
 *
 */
public enum OperatorEnum
{
    EQ(" = ")
    {
        @Override
        public ThreeTuple<String, Object, String> createOperate(DataBaseFieldMetadata field, Object value)
        {
            return this.defaultCreateOperate(field, value);
        }
    },
    NE(" <> ")
    {
        @Override
        public ThreeTuple<String, Object, String> createOperate(DataBaseFieldMetadata field, Object value)
        {
            return this.defaultCreateOperate(field, value);
        }
    },
    GT(" > ")
    {
        @Override
        public ThreeTuple<String, Object, String> createOperate(DataBaseFieldMetadata field, Object value)
        {
            return this.defaultCreateOperate(field, value);
        }
    },
    GTEQ(" >= ")
    {
        @Override
        public ThreeTuple<String, Object, String> createOperate(DataBaseFieldMetadata field, Object value)
        {
            return this.defaultCreateOperate(field, value);
        }
    },
    LT(" < ")
    {
        @Override
        public ThreeTuple<String, Object, String> createOperate(DataBaseFieldMetadata field, Object value)
        {
            return this.defaultCreateOperate(field, value);
        }
    },
    LTEQ(" <= ")
    {
        @Override
        public ThreeTuple<String, Object, String> createOperate(DataBaseFieldMetadata field, Object value)
        {
            return this.defaultCreateOperate(field, value);
        }
    },
    LIKE(" like ")
    {
        @Override
        public ThreeTuple<String, Object, String> createOperate(DataBaseFieldMetadata field, Object value)
        {
        	ThreeTuple<String, Object, String> result = new ThreeTuple<>();
            TwoTuple<Boolean, String> two = escapeParams(value);
            Object b = null;
            switch (field.getMatchModel())
            {
            case ALL:
                b = "%" + two.getB() + "%";
                break;
            case BEFORE:
                b = "%" + two.getB();
                break;
            case AFTER:
                b = two.getB() + "%";
                break;
            }
            String a = field.getColumnName() + getOperate();
            result.setA(a);
            result.setB(b);
            if (two.getA())
			{
				result.setC("escape '/'");
			} else 
			{
				result.setC("");
			}
            return result;
        }
    },
    LIKEIGNORECASE(" like ")
    {
        @Override
        public ThreeTuple<String, Object, String> createOperate(DataBaseFieldMetadata field, Object value)
        {
        	ThreeTuple<String, Object, String> result = new ThreeTuple<>();
            TwoTuple<Boolean, String> two = escapeParams(value);
            Object b = null;
            switch (field.getMatchModel())
            {
            case ALL:
                b = "%" + two.getB().toLowerCase(Locale.ENGLISH) + "%";
                break;
            case BEFORE:
                b = "%" + two.getB().toLowerCase(Locale.ENGLISH);
                break;
            case AFTER:
                b = two.getB().toLowerCase(Locale.ENGLISH) + "%";
                break;
            }
            String a = "lower(" + field.getColumnName() + ")" + getOperate();
            result.setA(a);
            result.setB(b);
            if (two.getA())
			{
				result.setC("escape '/'");
			} else 
			{
				result.setC("");
			}
            return result;
        }
    };

    private String operate;

    private OperatorEnum(String operate)
    {
        this.operate = operate;
    }

    public String getOperate()
    {
        return operate;
    }

    /**
     * 生成操作方式和值和附加属性（如escape）
     * @param field
     * @param value
     * @return
     */
    public abstract ThreeTuple<String, Object, String> createOperate(DataBaseFieldMetadata field, Object value);

    protected ThreeTuple<String, Object, String> defaultCreateOperate(DataBaseFieldMetadata field, Object value)
    {
        return new ThreeTuple<String, Object, String>(field.getColumnName() + getOperate(), value, "");
    }

    protected TwoTuple<Boolean, String> escapeParams(Object value)
    {
        if (value == null)
        {
            return new TwoTuple<Boolean, String>(false, "");
        }
        String valStr = value.toString();
        if (needEscape(valStr))
        {
            return new TwoTuple<Boolean, String>(true, X.matcher(H.matcher(B.matcher(valStr).replaceAll("/%")).replaceAll("/_")).replaceAll("//"));
        }
        return new TwoTuple<Boolean, String>(false, valStr);
    }

    protected final Pattern X = Pattern.compile("/");

    protected final Pattern B = Pattern.compile("%");

    protected final Pattern H = Pattern.compile("_");

    protected boolean needEscape(String value)
    {
        if (DaoUtil.isEmpty(value))
        {
            return false;
        }
        char[] arrayOfChar;
        int j = (arrayOfChar = ESCAPECHARS).length;
        for (int i = 0; i < j; i++)
        {
            char ch = arrayOfChar[i];
            if (value.indexOf(ch) > -1)
            {
                return true;
            }
        }
        return false;
    }
    
    protected final char[] ESCAPECHARS =
    { '%', '_' };

}
